# Description ------------------------------------------------------------------
#   This function takes the output from an felm model (object) and formats the
#   regression results using knitr's kable. The output is a table of
#   coefficients, as well as information about the number of observations,
#   the fixed effects, and the error clusterings.
#
#   Arguments
#     the_output: An felm-class object resulting from a call to felm().
#     the_digits: The number of digits desired in the outputted table of
#                   coefficients. The default is 4.
#     the_title:  Optional. Should be character vector. The title given to the
#                   outputted table. Include Markdown formatting if desired
#                   (e.g. "# Title").


# Function to make tables out of felm results ----------------------------------
  # The actual function
  table_felm <- function(the_output, the_digits = 4,
    the_title = NULL) {
    # Check for the required packages
    if(!("magrittr" %in% row.names(installed.packages())) |
    !("knitr" %in% row.names(installed.packages()))) {
      stop("The packages 'magrittr' and 'knitr' must be installed.")
    }
    # Load magrittr
    require(magrittr)
    # Take summary
    coef_matrix <- summary(the_output)$coef
    # Change column names
    colnames(coef_matrix) <- c("Coef.", "S.E.", "t Stat.", "p-Value")
    # Get row names
    r_names <- rownames(coef_matrix)
    # Change "(Intercept)" to "Intercept"
    r_names <- gsub("\\(Intercept\\)", "Intercept", r_names)
    # If a row name includes "I(" then remove "I(" and ")"
    targets <- grep("I\\(", r_names)
    if(length(targets) >= 1) {
      r_names[targets] <- gsub("I\\(", "", r_names[targets])
      r_names[targets] <- gsub("\\)", "", r_names[targets])
    }
    # Clean up exponents
    r_names <- gsub("\\^2", "_squared", r_names)
    r_names <- gsub("\\^3", "_cubed", r_names)
    # If a row name includes ":" change it to (...)x(...)
    targets <- grep("\\:", r_names)
    if(length(targets) >= 1) {
      r_names <- gsub("\\:", ")x(", r_names)
      r_names[targets] <- paste0("(", r_names[targets], ")")
    }
    # Change "_" to spaces
    r_names <- gsub("\\_", " ", r_names)
    # Delete apostrophes
    r_names <- gsub("\\`", "", r_names)
    r_names <- gsub("\\'", "", r_names)
    # Change "(fit)" to "(fitted)" and add leading space
    r_names <- gsub("\\(fit\\)", " \\(fitted\\)", r_names)
    # Change "dd" to "deg. days"
    r_names <- gsub("dd", "deg. days", r_names)
    # Change "t p" to "temp. bin"
    r_names <- gsub("t p", "temp. bin", r_names)
    # Change the row names
    rownames(coef_matrix) <- r_names
    # Conver to markdown via knitr's kable
    coef_md <- coef_matrix %>% knitr:::kable(digits = the_digits)
    # Outcome variable
    y_var <- gsub("_", " ", the_output$lhs)
    y_var <- paste0("__Outcome variable:__ ", y_var)
    # Get number of observations
    n_obs <- paste0("__Number of observations:__ ", the_output$N) %>% noquote()
    # If we use fixed effects, then get names
    if(length(names(the_output$fe)) > 0) {
      # Grab names of cluster variables
      fe_vars <- names(the_output$fe)
      # Change any underscores to spaces; separate with commas and spaces
      fe_vars <- gsub("_", " ", fe_vars) %>% paste(collapse = ", ")
      fe_vars <- paste0("__Fixed effects:__ ", fe_vars)
    } else {
      fe_vars <- "No fixed effects"
    }
    # If the errors are clustered, give the variables used to cluster
    if(length(names(the_output$clustervar)) > 0) {
      # Grab names of cluster variables
      cluster_vars <- names(the_output$clustervar)
      # Change any underscores to spaces; separate with commas and spaces
      cluster_vars <- gsub("_", " ", cluster_vars) %>% paste(collapse = ", ")
      cluster_vars <- paste0("__Errors clustered using:__ ", cluster_vars)
    } else {
      cluster_vars <- "Errors assumed I.I.D."
    }
    # Print results
    return(
      if(is.null(the_title)) {
        paste(c("\n", coef_md, "", y_var, "", n_obs, "",fe_vars, "",
          cluster_vars, "\n\n"), collapse = "\n") %>% noquote() %>% cat()
      } else {
        paste(c("\n", the_title, "", coef_md, "", y_var, "", n_obs, "", fe_vars,
          "", cluster_vars, "\n\n"), collapse = "\n") %>% noquote() %>% cat()
      })
  }
